/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.ac.iie.stream.commontools.registry;

import java.util.Collection;
import java.util.HashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *
 * @author zwlin
 * @param <ID> 标识类型，不可重复
 * @param <HANDLER> 处理器类型
 */
public class Registry<ID, HANDLER> {

	final HashMap<ID, Element<ID, HANDLER>> ElementMap;
	final ReentrantReadWriteLock mapLock;

	public Registry() {
		this.ElementMap = new HashMap<ID, Element<ID, HANDLER>>();
		this.mapLock = new ReentrantReadWriteLock();
	}

	public Registry(int initialCapacity) {
		this.ElementMap = new HashMap<ID, Element<ID, HANDLER>>(initialCapacity);
		this.mapLock = new ReentrantReadWriteLock();
	}

	public Registry(Collection<Element<ID, HANDLER>> elements) {
		this(elements.size());
		for (Element<ID, HANDLER> e : elements) {
			ElementMap.put(e.id, e);
		}
	}

	public Element<ID, HANDLER> RegistElement(Element<ID, HANDLER> e) {
		mapLock.writeLock().lock();
		try {
			return ElementMap.put(e.id, e);
		} finally {
			mapLock.writeLock().unlock();
		}
	}

	public Element<ID, HANDLER> UnregistElement(Element<ID, HANDLER> e) {
		mapLock.writeLock().lock();
		try {
			return ElementMap.remove(e.id);
		} finally {
			mapLock.writeLock().unlock();
		}
	}

	public Element<ID, HANDLER> GetElement(ID id) {
		mapLock.readLock().lock();
		try {
			return ElementMap.get(id);
		} finally {
			mapLock.readLock().unlock();
		}
	}

	static public class Element<ID, HANDLER> {

		private ID id;
		private HANDLER handler;

		public Element(ID id, HANDLER handler) {
			this.id = id;
			this.handler = handler;
		}

		/**
		 * @return the id
		 */
		public ID getId() {
			return id;
		}

		/**
		 * @param id the id to set
		 */
		public void setId(ID id) {
			this.id = id;
		}

		/**
		 * @return the handler
		 */
		public HANDLER getHandler() {
			return handler;
		}

		/**
		 * @param handler the handler to set
		 */
		public void setHandler(HANDLER handler) {
			this.handler = handler;
		}

	}

}
